チュートリアル 6: 基本的なシェープ グラマー

チュートリアル データ

チュートリアル データは、[Help] メニュー → [Download Tutorials and Examples…] を選択し、[CityEngine Tutorial] からダウンロードできます。

概要

CGA シェープグラマーは、CityEngine の中心をなす技術です。この機能を知ることは自分で建物や都市を構築する上で重要です。シンプルな建物の作成で、基本的なシェープ グラマーを学習します。

演習
Part 1 :シンプルな建物のモデリング
Part 2 :シンプルな建物へのテクスチャ貼り付け
Part 3 :LOD の追加
Part 4 :建物属性のランダム変化

Part 1 :シンプルな建物のモデリング

このセクションでは CityEngine の CGA シェープ グラマーの基本事項を学習します。基本的な建物を構築するための一通りのステップを含む完成したルール ファイルの中身を確認していきます。

チュートリアルのセットアップ

  1. プロジェクト Tutorial_06_Basic_Shape_Grammar を自分の CityEngine ワークスペースにインポートします。

  2. シーン Tutorial_06_Basic_Shape_Grammar/scenes/01_SimpleBuilding.cej を開きます。

シンプルな建物

ここでは、典型的な壁面を持ったシンプルな建物を構築します。Part 1 の最終成果物は以下のようになります。

  1. [3D View] ウィンドウにて区画 (すでにモデルが生成されている場合は生成されたもの) を選択し、Inspector (開いていない場合は [Window] メニュー → [Inspector] から開きます) ウィンドウを開きます。 ここで 2 つの重要なパラメーターがあります。
    • Rule File はルール ファイル rules/simpleBuilding.01.cga へのリンクです。このルール ファイルがモデル生成の実行時に使用されます。
    • Start Rule はルール ファイルの中で実行される最初のルールを定義しています。この場合のスタート ルールは Lot です。
  2. CGA ルール ファイルを見てみましょう。[Inspector] ウィンドウで Rule File リンクをクリックするか、[Navigator] ウィンドウで rules/simpleBuilding.01.cga ファイルをダブルクリックして [CGA Rule Editor] ウィンドウを開きます。

シンプルな建物のルールセット

建物属性

建物の属性情報は (ルール ファイル中のどこでも配置できますが) 通常はルール ファイルの最初の段階で定義されます。これらの属性はルール セット全体で使用され、[CGA Rule Editor] ウィンドウだけでなく、[Inspector] ウィンドウでも値を設定したり編集したりすることができます。

attr groundfloor_height = 4
attr floor_height = 3.5
attr tile_width = 3
attr height = 11
attr wallColor = "#fefefe"

窓のアセット

シンプルな建物の構築に使用される窓のアセットはここで定義されています。アセットは [Navigator] ウィンドウの中のプロジェクトの assets フォルダーから読み込まれます。

// geometries
window_asset = "facades/window.obj"

Lot ルール

これでもう建物の構築ができる状態です。最初のルールは Lot となっているはずです。[Inspector] ウィンドウで適用されている スタートルールを覚えておいてください。Extrude オペレーションを使用して立体モデルが作成されます。

Lot -->
	extrude(height) Building

Building ルール

通常このステップでは、Component 分割を適用することで立体モデルを壁面 (Facade) に分解します。

Building -->
	comp(f){ front : FrontFacade | side : SideFacade | top: Roof}

このルールでは、component 分割を適用することにより Building という名前の立体モデルの図形を面に分解します。これにより、前面 (玄関のある側の壁面) の図形、いくつかの側面の図形、屋根 (Roof) の図形ができます。

その後で壁面がモデリングされます。典型的な壁面モデリングのワークフローは次のようになっています。最初のステップで壁面はフロア (Floors) に分けられます。続いてフロアはさらに分解されて、タイル (Tiles)と呼ばれる要素に分けられます。1 つのタイルは壁と窓の要素で構成されています。この分割は CGA シェープグラマーの中で以下のように記述されています。

Front Façade ルール

FrontFacade ルールは、建物の前面を高さ 4 の一階のフロアの図形と、高さ 3.5 の 2 階以上をフロアの繰り返した (繰り返すためにはリピート オペレーター [*] を使用します) 図形に分割します。チルダ オペレーター [~] を使用すると、ビルの実際の高さにかかわらず、すべての上階のフロアが綺麗に配置されるように自動調節されます。特に前面については、1 階フロアの見た目は他のフロアと異なることが多くなります。例えば、1 階には玄関あり、2 階以上のフロアと比べると窓の様子や色なども異なります。

FrontFacade -->
	split(y){ groundfloor_height : Groundfloor | { ~floor_height: Floor }* }

Side Façade ルール

SideFacade ルールは、建物の側面をフロアに分割します。したがって、フロアの高さが前面と等しくなるように subdivision 分割が同様に実行されます。

SideFacade -->
	split(y){ groundfloor_height: Floor | { ~floor_height: Floor }* }

Floor ルール

Floor ルールは、フロアを幅およそ 3 のタイルに分割する典型的な例です。フロアのデザインをもう少し見栄え良くするために、壁要素の両端を幅 1 だけ分割します。

Floor -->
	split(x){ 1: Wall
		| { ~tile_width: Tile }*
		| 1 : Wall }

Ground Floor ルール

Groundfloor ルールは、地上フロアのシェープを、右側に玄関が付いた以外は同様の subdivision 分割で整えます。下図は、押し出しにより形成された立体モデル(左)とそれをフロアおよびタイルに分割した状態を示しています。

Groundfloor -->
	split(x){ 1: Wall
		|{ ~tile_width: Tile }*
		| ~tilewidth: EntranceTile
		| 1: Wall }

Tile ルール

初期的な前面の構造を定義したら、次はタイルをモデリングします。

Tile -->
	split(x){ ~1 : Wall
		| 2 : split(y){ 1: Wall | 1.5: Window | ~1: Wall }
		| ~1 : Wall }

Tile ルールは、x および y 軸方向に (入れ子状の split により) タイルを分割することによりタイルの見栄えを定義します。このデザインでは壁の要素は浮動的 (チルダが付いている) であり、また窓のサイズは幅 2、高さ 1.5 に固定されています。

Entrance Tile ルール

EntranceTile ルールは玄関のシェープをタイルの場合と同様に定義します (ただし底辺には壁は作りません)。

EntranceTile -->
	split(x){ ~1 : SolidWall
		| 2 : split(y){ 2.5: Door | ~2: SolidWall }
		| ~1 : SolidWall }

Window, Door, Wall ルール

最後のルールは、窓や扉や壁シェープの形状を対応するアセットで置き換え、適切に配置し、テクスチャをセットします。

Window -->
	s('1,'1,0.4)
	t(0,0,-0.25)
	i(window_asset)
Door -->
	s('1,'1,0.1)
	t(0,0,-0.5)
	i("builtin:cube")
Wall -->
	color(wallColor)
SolidWall -->
	color(wallColor)
	s('1,'1,0.4)
	t(0,0,-0.4)
	i("builtin:cube:notex")

オペレーション t(x,y,z) は現在のシェープの位置を z 軸方向に-0.25 移動する、ということになります。これにより、窓とテクスチャは壁面に 0.25m めり込んだ状態になります。この後、Insert オペレーション i(オブジェクト名) により現在のスコープにアセットが挿入されます。Window や Door ルールのようにディメンションが設定されていない場合は、自動的にサイズが適用されます。ディメンションが与えられている場合はそれが使用されます。オペレーション s(x,y,z) により、スコープのサイズが Wall ルールに設定されます。相対座標が使用されているため、スコープの幅や高さは影響を受けません。現在のスコープの x および y 方向は 1 倍にスケール (‘1) されますので結果的に何も変わりません。z 方向は -0.4 に設定されているため、結果的に 0.4m の厚さ(内側向き)を持った壁になります。

ここまでのルールを全て適用すると、テクスチャなしのシンプルな建物が完成します。 Part 2 では、このシンプルな建物モデルにテクスチャを貼り付ける方法を学習します。

Part 2 :シンプルな建物へのテクスチャ貼り付け

このセクションでは、シンプル建物の窓や壁にどのようにテクスチャを貼り付けるかを学習します。

チュートリアルのセットアップ

  1. Part 1 からの続きまたは、シーン Tutorial_06_Basic_Shape_Grammar/scenes/02_SimpleBuilding.cej を開きます。
  2. ルール ファイルを開きます。Part 1 で作成したルールをそのまま使用するか、[Navigator] ウィンドウの Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.02.cga ファイルをダブルクリックして [CGA Rule Editor] ウィンドウを起動します。

テクスチャの宣言

アセットと同様に、使用するテクスチャをルール ファイルの先頭で定義します。テクスチャは assets フォルダーから読み込まれます。

  1. 以下の行を自分のルール ファイルの window_asset の下に追加します。
// textures
frontdoor_tex = "facades/textures/shopdoor.tif"
wall_tex      = "facades/textures/brickwall.jpg"
dirt_tex      = "facades/textures/dirtmap.15.tif"
roof_tex      = "roofs/roof.tif"

assets/facade フォルダーには 9 つの異なる窓のテクスチャが用意されています。9 つのテクスチャすべてを単一のアセットとしてリストする代わりに、次の関数が 9 つの窓テクスチャのうちの 1 つを返します。

  1. 以下の行をルール ファイルに追加します。
randomWindowTexture = fileRandom("*facades/textures/window.*.tif")
  1. setupProjection() コマンドを Frontfacade および Sidefacade ルールに追加します。
Frontfacade -->
	setupProjection(0, scope.xy, 1.5, 1, 0, 0, 1)
	setupProjection(2, scope.xy, scope.sx, scope.sy)
	split(y){ groundfloor_height : Groundfloor | { ~floor_height: Floor }* }
Sidefacade -->
	setupProjection(0, scope.xy, 1.5, 1, 0, 0, 1)
	setupProjection(2, scope.xy, scope.sx, scope.sy)
	split(y){ groundfloor_height: Floor | { ~floor_height: Floor }* }

setupProjection() コマンドは、スコープの xy 平面に投影された色 (チャンネル0) とダートマップ (チャンネル1)を建物前面上の UV 座標へ投影する準備をします。したがって scope.xy が第2 パラメーターとしてセットされています。ブロックのテクスチャ (チャンネル0) は X 方向に 1.5m ごと、Y 方向に 1m ごとに繰り返されます。一方、ダートマップ (チャンネル2) は建物前面全体にわたっており、そのために scope.sx および scope.sy がサイズ パラメーターとして使用されています。

  1. 新しいルール Roof の追加
Roof -->
	setupProjection(0, scope.xy, scope.sx, scope.sy)
	texture(roof_tex)
	projectUV(0)

Roof ルールは屋根の面全体に適用される UV 座標を準備し、屋根のテクスチャをセットし、ジオメトリにテクスチャ座標を適用します。

  1. 後続のルールにtexture() コマンドを追加します。
Window -->
	s('1,'1,0.4)
	t(0,0,-0.25)
	texture(randomWindowTexture)
	i(window_asset)
Door -->
	s('1,'1,0.1)
	t(0,0,-0.5)
	texture(frontdoor_tex)  
	i("builtin:cube")

窓(Window)と扉(Door)の要素に対しては要求されるテクスチャにカラーマップのみをセットします。窓については getWindowTex() 関数をランダムなインデックスとともに使用し、9 つの窓テクスチャのうちの 1 つを取得します。

  1. Wall および SolidWall では Facade ルールで準備された UV が使用されます。色およびダートチャンネルの選択に加え、UV をこれら 2 つのチャンネルに投影する必要もあります。
Wall -->
	color(wallColor)
	texture(wall_tex)  
	set(material.dirtmap, dirt_tex)
	projectUV(0) projectUV(2)

SolidWall -->
	color(wallColor)
	s('1,'1,0.4) 
	t(0,0,-0.4) 
	texture(wall_tex)  
	set(material.dirtmap, dirt_tex)
	i("builtin:cube:notex")	
	projectUV(0) projectUV(2)

下図は壁とアセットにテクスチャを貼り込んだ最終形のモデルです。 同じモデルを拡大した状態: 任意の立体モデルにこのルールセットを適用: Part 3 では LOD(Level Of Detail、詳細レベル)を追加します。

Part 3 :LOD の追加

このセクションでは、ここまでに作成したシンプルな建物に対して簡単な LOD(詳細度)を追加します。モデルの複雑さ(ポリゴン数)を省略することができるため、シンプルな建物をより広範囲で作成する場合に有効です。

チュートリアルのセットアップ

  1. Part 2 からの続きまたは、シーン Tutorial_06_Basic_Shape_Grammar/scenes/02_SimpleBuilding.cej を開きます。
  2. ルール ファイルを開きます。Part 2 で作成したルールをそのまま使用するか、[Navigator] ウィンドウの Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.02.cga ファイルをダブルクリックして [CGA Rule Editor] ウィンドウを起動します。

LOD 属性の追加

新しい属性 LOD を CGA ファイルの既存の属性に追加します。

attr LOD = 1

この例では、2 つの詳細度のみを定義します。

  • LOD 0 : 低い詳細度、複雑さの程度も低い
  • LOD 1 : 高い詳細度、複雑さの程度が高い

ここまでに作成したシンプル建物は、高解像度モデルになります。これからいくつかのステップにより低解像度バージョンを作成します。

再び現在のモデルを見てみると、窓 (Window) アセットのポリゴンを省略できそうです。複雑な窓アセットの代わりにテクスチャを貼った平面を使用します。

  1. Window ルールの 最初の行に case LOD > 0:else の引数に texture(randomWindowTexture) を以下のように追加します。
Window -->
	case LOD > 0 : 
	  s('1,'1,0.4)
	  t(0,0,-0.25)
	  texture(randomWindowTexture)
	  i(window_asset)  
	else :		
	  setupProjection(0,scope.xy,scope.sx,scope.sy)	
	  texture(randomWindowTexture)	
	  projectUV(0)

ここでは Window ルールに条件を追加しました。LOD 値が 0 よりも大きければ (つまり高解像度モデルなら)、元々ある高解像度アセットを使用します。そうでない場合 (LOD が 0) は、窓アセットは読み込まずに建物前面に由来する単純な平面を使用します。

  1. Door ルールについても同様です。立体の代わりに単純な平面を読み込みます。
Door -->
	case LOD > 0 :
  s('1,'1,0.1)
	 t(0,0,-0.5)
  texture(frontdoor_tex)
   i("builtin:cube")
	else :
	 setupProjection(0,scope.xy,scope.sx,scope.sy)	
	 texture(frontdoor_tex) 
	 projectUV(0)
  1. さらに SolidWall 要素についても同様です。扉のはめ込みを取り除いたため、立体的な要素は必要なくなりました。
SolidWall -->
	case LOD > 0 :
	    color(wallColor)
	    s('1,'1,0.4) 
	    t(0,0,-0.4) 
	    texture(wall_tex)  
	    set(material.dirtmap, dirt_tex)
	    i("builtin:cube:notex")	
	    projectUV(0) projectUV(2)
    else :
	    Wall
  1. 建物を選択した状態で [Inspector] ウィンドウ内の属性フィールドを見てみましょう。先ほど追加したばかりの LOD 属性があるはずです。値を 0 に変更します。Source フィールドは Rules から Value へ変化しています。これは、次の建物の生成時にはルール ファイル内の建物の LOD 値が [Inspector] ウィンドウで 0 に設定されることを意味します。

ソースフィールドが [ルール] から [値] に変わります。これは、次世代の建物では、ルールファイルの LOD 値がインスペクターの値 0 によって設定されることを意味します。 次のスクリーンショットは、LOD = 0 のインスペクターの新しい LOD 属性を示しています。

  1. 建物を生成すると、以下のような LOD が 0 の低解像度バージョンで生成されます。

  2. モデルを Wireframe on shaded (7 キーを押す) および Untextured (5 キー) で表示すると、両者の違いが明確になります。ポリゴン数を確認するために D キーを押してヘッドアップ ディスプレイを表示します。モデルを構成するポリゴンの数が 3699 から 475 に減少したことがわかります。

Part 4 ではシンプル建物にランダムな変化を追加します。

Part 4 :建物属性のランダム変化

このセクションでは、ランダム属性を定義することにより建物の生成に変化をつける方法を学習します。

チュートリアルのセットアップ

  1. Part 3 からの続きまたは、シーン Tutorial_06_Basic_Shape_Grammar/scenes/02_SimpleBuilding.cej を開きます。
  2. ルール ファイルを開きます。Part 1 で作成したルールをそのまま使用するか、[Navigator] ウィンドウの Tutorial_06_Basic_Shape_Grammar/rules/simpleBuilding.03.cga ファイルをダブルクリックして [CGA Rule Editor] ウィンドウを起動します。

ランダム属性の追加

  1. これまでに作成した建物の属性のうちの 3 つに変化をつけます。タイル幅を 2.5 から 6 メートルの間で、高さを 8 から 35 メートルの間で、建物の色を 3 色の中からランダムに設定し、各建物に適用します。
attr tile_width	= rand(2.5, 6)
attr height		= rand(8, 35) 
attr wallColor	= 33%  :  "#ffffff"
                  33%  :  "#999999"
                  else :  "#444444"
  1. 大量の建物を生成するため、デフォルト LOD 値を 1 から 0 に変更します。
attr LOD = 0
  1. レイヤー Lots 2 を選択します。

  2. [Shapes] メニュー → [Generate] で建物を生成します。